FUZZER_NAME := 'fuzzer_libpng_launcher'
PROJECT_DIR := absolute_path(".")
PROFILE := env("PROFILE", "release")
PROFILE_DIR := if PROFILE == "release" { "release" } else if PROFILE == "dev" { "debug" } else { "debug" }
CARGO_TARGET_DIR := env("CARGO_TARGET_DIR", "target")
FUZZER := PROJECT_DIR / CARGO_TARGET_DIR / PROFILE_DIR / FUZZER_NAME
LIBAFL_CC := PROJECT_DIR / CARGO_TARGET_DIR / PROFILE_DIR / "libafl_cc"
LIBAFL_CXX := PROJECT_DIR / CARGO_TARGET_DIR / PROFILE_DIR / "libafl_cxx"
LIBTOOL := PROJECT_DIR / CARGO_TARGET_DIR / PROFILE_DIR / "libafl_libtool"


alias cc := cxx

[linux]
[macos]
libpng:
    #!/bin/bash
    if [ ! -f v1.6.37.tar.gz ]; then
        wget https://github.com/glennrp/libpng/archive/refs/tags/v1.6.37.tar.gz
    fi
    tar -xvf v1.6.37.tar.gz

[windows]
libpng:
    echo "Unsupported on this platform"

[linux]
[macos]
cxx:
    cargo build --profile {{PROFILE}}

[windows]
cxx:
    echo "Unsupported on this platform"

[linux]
[macos]
lib: libpng cxx
    #!/bin/bash
    if [ ! -f libpng-1.6.37/.libs/libpng16.a ]; then
        cd libpng-1.6.37 && CC={{LIBAFL_CC}} CXX={{LIBAFL_CXX}} ./configure --enable-shared=no --with-pic=yes --enable-hardware-optimizations=no
    else
        echo "libpng already built, skipping configure..."
    fi
    cd {{PROJECT_DIR}}
    make -C libpng-1.6.37 libpng16.la CC="{{LIBAFL_CC}}" CXX="{{LIBAFL_CXX}}" LIBTOOL="{{LIBTOOL}}"

[windows]
lib:
    echo "Unsupported on this platform"

[linux]
[macos]
fuzzer: lib cxx
    {{LIBAFL_CXX}} {{PROJECT_DIR}}/harness.cc {{PROJECT_DIR}}/libpng-1.6.37/.libs/libpng16.a -I {{PROJECT_DIR}}/libpng-1.6.37/ -o {{FUZZER_NAME}} -lm -lz

[windows]
fuzzer:
    echo "Unsupported on this platform"

[linux]
[macos]
run: fuzzer
    ./{{FUZZER_NAME}}.coverage --broker-port 21337 --cores 0 --input ./corpus

[windows]
run: fuzzer
    echo "Unsupported on this platform"

[linux]
[macos]
test: fuzzer test-statsd
    #!/bin/bash
    rm -rf libafl_unix_shmem_server || true
    timeout 31s ./{{FUZZER_NAME}}.coverage --broker-port 21337 --cores 0 --input ./corpus  2>/dev/null | tee fuzz_stdout.log || true
    if grep -qa "corpus: 30" fuzz_stdout.log; then
        echo "Fuzzer is working"
    else
        echo "Fuzzer does not generate any testcases or any crashes"
        exit 1
    fi

[windows]
test: fuzzer
    echo "Unsupported on this platform"

[linux]
[macos]
cxx-statsd:
    cargo build --profile {{PROFILE}} --features statsd

[linux]
[macos]
fuzzer-statsd: lib cxx-statsd
    {{LIBAFL_CXX}} {{PROJECT_DIR}}/harness.cc {{PROJECT_DIR}}/libpng-1.6.37/.libs/libpng16.a -I {{PROJECT_DIR}}/libpng-1.6.37/ -o {{FUZZER_NAME}}-statsd -lm -lz

[linux]
[macos]
test-statsd: fuzzer-statsd
    #!/bin/bash
    rm -rf libafl_unix_shmem_server || true
    rm -f statsd_out.log
    # Start python listener in background
    python3 -c "import socket; s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.bind(('127.0.0.1', 8126)); s.settimeout(25); d=s.recv(1024); print(d)" > statsd_out.log &
    LISTENER_PID=$!
    # Run fuzzer for a few seconds
    timeout 20s ./{{FUZZER_NAME}}-statsd --broker-port 21338 --cores 0 --input ./corpus --statsd --statsd-port 8126 > fuzzer_statsd.log 2>&1 || true
    # Wait for listener to potentially finish if it got data
    wait $LISTENER_PID || true
    if [ -s statsd_out.log ]; then
        echo "StatsD received data"
    else
        echo "StatsD failed to receive data"
        exit 1
    fi


clean:
    rm -rf {{FUZZER_NAME}}
    make -C libpng-1.6.37 clean || true
    cargo clean

